//go:build ignore
// +build ignore

package main

import (
	"fmt"
	"os/exec"
	"regexp"
	"strings"

	"github.com/blang/semver"
)

// getTag 通过Git命令获取标签信息并解析预发布版本
// 参数match用于传递git describe命令的额外匹配参数
// 返回值：
//
//	string: 基础标签版本
//	*semver.PRVersion: 预发布版本信息（如果有）
func getTag(match ...string) (string, *semver.PRVersion) {
	args := append([]string{
		"describe", "--tags",
	}, match...)
	if tag, err := exec.Command("git", args...).Output(); err != nil {
		return "", nil
	} else {
		tagParts := strings.Split(string(tag), "-")
		if len(tagParts) == 3 {
			ahead, err := semver.NewPRVersion(tagParts[1])
			if err == nil {
				return tagParts[0], &ahead
			}
			// 静默处理预发布版本解析错误
			_ = err
		} else if len(tagParts) == 4 {
			ahead, err := semver.NewPRVersion(tagParts[2])
			if err == nil {
				return tagParts[0] + "-" + tagParts[1], &ahead
			}
			// 静默处理预发布版本解析错误
			_ = err
		}

		return string(tag), nil
	}
}

// parseFallbackVersion 从输入字符串提取数字并格式化为vX.X.X格式
// 当语义化版本解析失败时作为回退方案
func parseFallbackVersion(input string) string {
	// 提取所有数字序列
	re := regexp.MustCompile(`\d+`)
	numStrs := re.FindAllString(input, -1)

	// 确保至少有三个数字部分，不足则补0
	nums := make([]string, 3)
	for i := 0; i < 3; i++ {
		if i < len(numStrs) && numStrs[i] != "" {
			nums[i] = numStrs[i]
		} else {
			nums[i] = "0"
		}
	}

	return fmt.Sprintf("v%s.%s.%s", nums[0], nums[1], nums[2])
}

// main 程序入口点，生成并输出版本号
// 流程：
// 1. 获取最新版本标签和提交超前数量
// 2. 解析语义化版本
// 3. 处理发布版本和开发版本的不同情况
// 4. 构建并输出版本字符串
func main() {
	// Find the last vX.X.X Tag and get how many builds we are ahead of it.
	versionStr, ahead := getTag("--match", "v*")
	version, err := semver.ParseTolerant(versionStr)
	if err != nil {
		// 解析失败，使用回退方案生成版本号
		// 静默处理解析错误，不输出日志
		_ = err
		fallbackVersion := parseFallbackVersion(versionStr)
		fmt.Println(fallbackVersion)
		return
	}
	// Get the tag of the current revision.
	tag, _ := getTag("--exact-match")
	if tag == versionStr {
		// Seems that we are going to build a release.
		// So the version number should already be correct.
		fmt.Printf("v%d.%d.%d\n", version.Major, version.Minor, version.Patch)
		return
	}

	// If we don't have any tag assume "dev"
	if tag == "" || strings.HasPrefix(tag, "nightly") {
		tag = "dev"
	}
	// Get the most likely next version:
	if !strings.Contains(version.String(), "rc") {
		version.Patch = version.Patch + 1
	}

	if pr, err := semver.NewPRVersion(tag); err == nil {
		// append the tag as pre-release name
		version.Pre = append(version.Pre, pr)
	} else {
		// 静默处理预发布版本解析错误
		_ = err
	}

	if ahead != nil {
		// if we know how many commits we are ahead of the last release, append that too.
		version.Pre = append(version.Pre, *ahead)
	}

	fmt.Printf("v%d.%d.%d\n", version.Major, version.Minor, version.Patch)
}
